#include "joueuriafacile.h"

#include "case.h"
#include "ia.h"

#include <QtCore/QtConcurrentRun>
#include <QtCore/QDebug>
#include <QtCore/QFuture>
#include <QtCore/QMap>

JoueurIAFacile::JoueurIAFacile(int pNumero, const QString& pNom) : Joueur(pNumero, pNom) {
}

int JoueurIAFacile::jouer(const Plateau& pEtat) {
	int max = -1000;
	int numCaseDep = (numero() == 1 ? 0 : 6);
	int numCaseFin = (numero() == 1 ? 5 : 11);
	int pos = numCaseFin;

	QMap<int, QFuture<int> > threads;
	for (int i = numCaseDep; i <= numCaseFin; ++i) {
		if (pEtat.m_cases[i]->nbGraines() > 0) {
			Plateau etatFinal;
			int nbGrainesPrises = pEtat.simulerCoup(i, etatFinal);
			QFuture<int> f = QtConcurrent::run(this, &JoueurIAFacile::min, etatFinal, 6, nbGrainesPrises, 0);
			threads.insert(i, f);
		}
    }

	QMapIterator<int, QFuture<int> > it (threads);
	while (it.hasNext()) {
		it.next();
		if (it.value().result() > max) {
			max = it.value().result();
			pos = it.key();
		}
	}

	qDebug() << "IA facile " << numero() << " joue en " << pos << " et a maintenant " << nbGraines() << " graines";
	return pos;
}

int JoueurIAFacile::min(const Plateau& pEtat, int pProfondeur, int pNbPrisesJoueur, int pNbPrisesAdversaire) const {
	if (pProfondeur == 0) {
		return eval(pEtat, pNbPrisesJoueur, pNbPrisesAdversaire, numero());
	} else {
		int min = 500;
		int nbCasesVides = 0;
		int tmp;
		int numCaseDep = (numero() == 2 ? 0 : 6);
		int numCaseFin = (numero() == 2 ? 5 : 11);

		for (int i = numCaseDep; i <= numCaseFin; ++i) {
			if (pEtat.m_cases[i]->nbGraines() > 0) {
				Plateau etatFinal = pEtat;
				int nbGrainesPrises = pEtat.simulerCoup(i, etatFinal);

				tmp = max(etatFinal, pProfondeur - 1, pNbPrisesJoueur, pNbPrisesAdversaire + nbGrainesPrises);

				if (tmp < min) {
					min = tmp;
				}
			} else {
				++nbCasesVides;
			}
		}

		return (nbCasesVides == 6 ? pNbPrisesJoueur - pNbPrisesAdversaire : min);
	}
}

int JoueurIAFacile::max(const Plateau& pEtat, int pProfondeur, int pNbPrisesJoueur, int pNbPrisesAdversaire) const {
	if (pProfondeur == 0) {
		return eval(pEtat, pNbPrisesJoueur, pNbPrisesAdversaire, numero());
	} else {
		int max = -100;
		int nbCasesVides = 0;
		int tmp;
		int numCaseDep = (numero() == 1 ? 0 : 6);
		int numCaseFin = (numero() == 1 ? 5 : 11);

		for (int i = numCaseDep; i <= numCaseFin; ++i) {
			if (pEtat.m_cases[i]->nbGraines() > 0) {
				Plateau etatFinal = pEtat;
				int nbGrainesPrises = pEtat.simulerCoup(i, etatFinal);

				tmp = min(etatFinal, pProfondeur - 1, pNbPrisesJoueur + nbGrainesPrises, pNbPrisesAdversaire);

				if (tmp > max) {
					max = tmp;
				}
			} else {
				++nbCasesVides;
			}
		}

		return (nbCasesVides == 6 ? pNbPrisesJoueur - pNbPrisesAdversaire : max);
	}
}
